package com.ibm.psbc.cloud.common.contextcarrier;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



/**
 * 工具类用于辅助Context创建转换等。
 * 各应用必须定义一个本类的实例，指定Context的实际类。如：<br/>
 * &#064;Bean<br/>
    ContextUtils<TestContext> getContextUtils(){<br/>
    &nbsp;&nbsp;	return new ContextUtils<TestContext>(MyContext.class);<br/>
    }<br/>
 * @author johnny
 *
 * @param <T> Context的实际类
 */
public class ContextUtils<T> {
	static Logger logger = LoggerFactory.getLogger(ContextUtils.class);
	public final static String CONTEXT_HEAD_PREFIX = "Context";
	/**
	 * Context的实际类，初始化ContextUtils时要指定。
	 */
	private final Class<T> contextClass;
	
	public ContextUtils(Class<T> contextClass) {
		super();
		this.contextClass = contextClass;
	}
	/**
	 * 把当前的Context转换成Map，按bean properties规则，如bean.prop1.name=123, bean.prop2[0].key=abc
	 * @return
	 */
	public Map<String, String> context2Map() {
	    ThreadLocal<T> t = new ThreadLocal<T>();
	    T context = t.get();
	    HashMap<String, String> data = new HashMap<String, String>();
	    BeanMapUtils.copyBean2Map(context, data, CONTEXT_HEAD_PREFIX);
	    return data;
	}
	/**把请求头中的相关信息，转换到当前线程的Context中去。
	 * @param request 请求实例
	 */
	public void header2Context(HttpServletRequest request) {
		HashMap<String, String> data = new HashMap<String, String>();
		 Iterator<String> it = request.getHeaderNames().asIterator();
		while (it.hasNext()) {
				String hname = it.next();
				if (hname.startsWith(CONTEXT_HEAD_PREFIX)) {
					data.put(hname, request.getHeader(hname));
				}
		}
		map2Conext(data);
		
	}
	/**
	 * 把map中的数据转换到当前Context中
	 * @param data 数据Map
	 */
	public void map2Conext(HashMap<String, String> data) {
		ThreadLocal<T> t = new ThreadLocal<T>();
	    T context = t.get();
	    if (context == null) {
	    	try {
	    		context = contextClass.getDeclaredConstructor().newInstance();
	    		t.set(context);
	    		logger.debug("New Context set to thread local");
			} catch (Exception e) {
				throw new RuntimeException("Cannot initialize "+ contextClass, e);
			}
	    }
	    BeanMapUtils.copyMap2Bean(data, context, CONTEXT_HEAD_PREFIX);
	}
}
